package net.dipper.tankwar.game.ui;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.IOException;
import java.util.ArrayList;

import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import net.dipper.tankwar.core.config.ConfigItem;
import net.dipper.tankwar.core.config.ConfigManager;
import net.dipper.tankwar.core.config.ObjectItem;
import net.dipper.tankwar.core.data.Bullet;
import net.dipper.tankwar.core.data.ObjectMap;
import net.dipper.tankwar.core.helper.ViewPort;
import net.dipper.tankwar.game.control.GameRule;
import net.dipper.tankwar.game.helper.Message;
import net.dipper.tankwar.game.helper.MessageManager;

import wnb.util.io.ImageManager;
import wnb.util.ui.Animation;
import wnb.util.ui.AnimationHelper;

public class GameAnimation implements Animation {
	private GameContext context;
	private ConfigManager config;

	public GameAnimation(GameContext context){
		try {
			this.context = context;
			this.config = ConfigManager.getInstance();
		} catch (ClassNotFoundException | InstantiationException
				| IllegalAccessException | ParserConfigurationException
				| SAXException | IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void paintFrame(Graphics2D g2, int width, int height, int frameIndex) {
		try{
			ObjectMap map = context.getMap();
			ViewPort vp = context.getViewPort();
			int gW = width / vp.width;
			int gH = height / vp.height;
			
			drawBackground(map.getBackgroundMap(), g2, gW, gH, vp.x, vp.y, vp.width, vp.height);
			drawUnit(map.getObjectMap(), g2, gW, gH, vp.x, vp.y, vp.width, vp.height);
			drawBullet(map.getBullets(), g2, gW, gH, vp.x, vp.y, vp.width, vp.height);
			drawMessages(map, MessageManager.getInstance(), g2, gW, gH, width, height);
		}catch(IOException | ClassNotFoundException | InstantiationException | IllegalAccessException | ParserConfigurationException | SAXException ex){
			ex.printStackTrace();
		}
	}

	//绘制消息
	private void drawMessages(ObjectMap map, MessageManager manager,
			Graphics2D g2, int gW, int gH, int width, int height) throws ClassNotFoundException, InstantiationException, IllegalAccessException, ParserConfigurationException, SAXException, IOException {
		ArrayList<Message> messages = manager.getMessages();
		for(Message message : messages){
			switch(message.getMessageType()){
			case Message.HEALTH_DECREASE:
				drawHealthDecreaseMessage(map, message, g2, gW, gH);
				break;
				
			case Message.GAME_RESULT:
				drawResult(g2, Byte.parseByte(message.getContent()), width, height);
				break;
			}
			
			int lifeTime = message.stepLifeTime();
			if(lifeTime == 0){
				manager.remove(message);
			}
		}
	}

	//绘制生命值减少消息
	private void drawHealthDecreaseMessage(ObjectMap map, Message message,
			Graphics2D g2, int gW, int gH) throws ClassNotFoundException, InstantiationException, IllegalAccessException, ParserConfigurationException, SAXException, IOException {
		int x = message.getX();
		int y = message.getY();
		byte value = map.getObject(x, y);
		ConfigManager manager = ConfigManager.getInstance();
		ObjectItem item = (ObjectItem) manager.getObject(value);
		if(item != null){
			int fullVal = item.getDefendence();
			int currentVal = map.getHealth(x, y);
			ViewPort port = context.getViewPort();
			
			g2.setPaint(Color.GRAY);
			g2.drawRect(gW * (x - port.x), gH * (y - port.y), gW, 8);
			
			g2.setPaint(Color.GREEN);
			g2.fillRect(gW * (x - port.x) + 1, gH * (y - port.y) + 1, gW * currentVal / fullVal - 2, 6);
		}
	}

	//绘制游戏结果
	private void drawResult(Graphics2D g2, byte result, int width, int height){
		String msgStr = "";
		switch(result){
		case GameRule.RESULT_FAIL:
			msgStr = "游戏失败";
			break;
			
		case GameRule.RESULT_SUCCESS:
			msgStr = "游戏成功";
			break;
		}

		Font font = new Font(Font.SANS_SERIF,  Font.PLAIN, 50);
		g2.setFont(font);		
		FontMetrics metrics = g2.getFontMetrics(font);
		int strWidth = metrics.stringWidth(msgStr);
		int x = (width - strWidth) / 2;
		int y = 200;

		g2.setPaint(Color.WHITE);
		g2.drawString(msgStr, x - 2, y);
		g2.drawString(msgStr, x + 2, y);
		g2.drawString(msgStr, x, y - 2);
		g2.drawString(msgStr, x, y + 2);
		g2.setPaint(Color.BLACK);
		g2.drawString(msgStr, x, y);
	}
	
	//绘制子弹
	private void drawBullet(ArrayList<Bullet> bullets, Graphics2D g2, int gW,
			int gH, int x, int y, int width, int height) {
		if(bullets == null || bullets.size() == 0)
			return;
		
		for(Bullet bullet : bullets){
			double posX = bullet.getPosX();
			double posY = bullet.getPosY();
			int dx = (int) (gW * (posX - x));
			int dy = (int) (gH * (posY - y));
			
			if(dx >= 0 && dx < gW * width && dy >= 0 && dy < gW * height){
				g2.setPaint(getBulletColor(bullet));
				g2.fillArc(dx -3, dy - 3, 6, 6, 0, 360);
			}
		}
	}

	private Color getBulletColor(Bullet bullet) {
		int value = bullet.getValue();
		if(value < 3)
			return Color.WHITE;
		else if(value < 5)
			return Color.YELLOW;
		else if(value < 9)
			return Color.ORANGE;
		else
			return Color.RED;
	}

	private void drawUnit(byte[][] map, Graphics2D g2, int gW, int gH,
			int x, int y, int width, int height) throws IOException {
			for(int i=x; i < x + width; i++){
				for(int j = y; j < y + height; j++){
					ConfigItem item = config.getObject(map[i][j]);
					if(item == null)
						continue;
					
					byte direction = context.getMap().getDirection(i, j);
					Image img = ImageManager.getImage(item.getImg());
					switch(direction){
					case ObjectMap.DIRECTION_E:
						g2.drawImage(AnimationHelper.rotate(img, 90), gW * (i - x), gH * (j - y), gW, gH, null);
						break;
						
					case ObjectMap.DIRECTION_N:
						g2.drawImage(img, gW * (i - x), gH * (j - y), gW, gH, null);
						break;
						
					case ObjectMap.DIRECTION_S:
						g2.drawImage(AnimationHelper.rotate(img, 180), gW * (i - x), gH * (j - y), gW, gH, null);
						break;
						
					case ObjectMap.DIRECTION_W:
						g2.drawImage(AnimationHelper.rotate(img, 270), gW * (i - x), gH * (j -y), gW, gH, null);
						break;
					}
				}
			}
	}

	//绘制背景层
	private void drawBackground(byte[][] map, Graphics2D g2, int gW, int gH, int x, int y, int width, int height) throws IOException {
		for(int i=x; i < x + width; i++){
			for(int j = y; j < y + height; j++){
				ConfigItem item = config.getBackground(map[i][j]);
				if(item == null)
					continue;
				
				Image img = ImageManager.getImage(item.getImg());
				g2.drawImage(img, gW * (i - x), gH * (j - y), gW, gH, null);
			}
		}
	}

	@Override
	public int getFrameCount() {
		return 0;
	}

}
